package com.razorfish.configuration.parsers 
{
	import com.razorfish.configuration.entities.ConfigObjectType;
	import com.razorfish.configuration.entities.Item;
	import com.razorfish.configuration.entities.PredefinedProperty;
	import com.razorfish.configuration.entities.Property;
	import com.razorfish.configuration.entities.SingleConfigObject;
	import com.razorfish.configuration.entities.KeyTypePair;
	
	/**
	 * ...
	 * @author heartAce
	 */
	public class UnknownValue 
	{
		public var valueList:Vector.<String>;
		public var pairList:Vector.<KeyTypePair>;
		public var isKnown:Boolean;
		public var value:String;
		public var orginalData:String;
		
		public function UnknownValue(data:String)
		{
			this.orginalData = data;
			parse();
		}
		
		private function parse():void
		{
			pairList = new Vector.<KeyTypePair>();
			var startAndLenArr:Array = [];
			
			var regex:RegExp = /(\$\(([^)]+?)\))|(\@\(([^)]+?)\))/g;
			var result:Object = regex.exec(orginalData);
			var unmatch:Boolean = true;
			var index:int = 0;
			while (result != null)
			{
				if (unmatch) unmatch = false;
				
				if (result.length == 5)
				{
					startAndLenArr.push([result.index, result[0].length]);
					var type:String = (result[3] == undefined && result[4] == undefined) ? ConfigObjectType.Property : ConfigObjectType.Item;
					var itemName:String = type == ConfigObjectType.Property ? result[2] : result[4];
					var itemPair:KeyTypePair = new KeyTypePair(itemName, type, index++);
					pairList.push(itemPair);
					result = regex.exec(orginalData);
				}
			}
			
			if (unmatch)
			{
				isKnown = true;
				value = this.orginalData;
			}
			else
			{
				valueList = new Vector.<String>();
				var record:int = 0;
				var listLen:int = 0;
				for (var j:int = 0; j < startAndLenArr.length; j++)
				{
					var startAndLen:Array = startAndLenArr[j];
					var start:int = startAndLen[0];
					var len:int = startAndLen[1];
					
					if (record < start)
					{
						valueList[listLen++] = orginalData.substr(record, start - record);
						record = start;
					}
					
					valueList[listLen++] = undefined;
					record = start + len;
					
					if (j == startAndLenArr.length - 1)
					{
						if (record < orginalData.length)
							valueList[listLen++] = orginalData.substr(record);
					}
				}
			}
		}
		
		public function tryGetValue():void
		{
			if (isKnown) return;
			else
			{
				if (valueList != null)
				{
					var undefIndex:int = 0;
					for (var i:int = 0; i < valueList.length; i++)
					{
						if (valueList[i] != null)
							continue;
						else
						{
							if (pairList.length == 0) return;
							
							var pair:KeyTypePair = pairList[undefIndex];
							if (pair.type == ConfigObjectType.Property)
							{
								if (PredefinedProperty.isDefined(pair.key))
								{
									valueList[i] = PredefinedProperty.getProperty(pair.key);
									pairList.splice(undefIndex, 1);
								}
								else
								{
									var arr:Array = SingleConfigObject.getProperty(pair.key);
									if (arr == null || arr.length == 0)
									{
										//
									}
									else if (arr.length > 1)
									{
										undefIndex++;
									}
									else if (arr.length == 1)
									{
										var p:Property = arr[0] as Property;
										if (p.parent.isAvailable)
										{
											p.tryGetValue();
											if (p.isValueReady)
											{
												valueList[i] = p.value;
												pairList.splice(undefIndex, 1);
											}
											else
											{
												undefIndex++;
											}
										}
										else
										{
											undefIndex++;
										}
									}
								}
							}
							else if (pair.type == ConfigObjectType.Item)
							{
								var itemArr:Array = SingleConfigObject.getItem(pair.key);
								if (itemArr == null || itemArr.length == 0)
								{
									//
								}
								else if (itemArr.length > 1)
								{
									undefIndex++;
								}
								else if (itemArr.length == 1)
								{
									var item:Item = itemArr[0] as Item;
									if (item.parent.isAvailable)
									{
										item.tryGetValue();
										if (item.isValueReady)
										{
											valueList[i] = item.value;
											pairList.splice(undefIndex, 1);
										}
									}
									else
									{
										undefIndex++;
									}
								}
							}
						}
					}
					
					if (pairList.length == 0)
					{
						isKnown = true;
						value = valueList.join("");
					}
				}
			}
		}
	}
}
